package com.winning.pmph.utils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.winning.pmph.entity.*;
import com.winning.pmph.mapper.FieldCompareMapper;
import com.winning.pmph.mapper.LastEditedFieldMapper;
import com.winning.pmph.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @author wu_di@winning.com.cn
 * @date 2020/11/2
 */
@Slf4j
public class FieldCompareUtil {

    private static TagService tagService = ApplicationContextUtil.getBean(TagService.class);
    private static UserService userService = ApplicationContextUtil.getBean(UserService.class);
    private static RuleItemService ruleItemService = ApplicationContextUtil.getBean(RuleItemService.class);
    private static TempKnowledgeFieldService tempKnowledgeFieldService = ApplicationContextUtil.getBean(TempKnowledgeFieldService.class);
    private static ReleasedKnowledgeFieldService releasedKnowledgeFieldService = ApplicationContextUtil.getBean(ReleasedKnowledgeFieldService.class);
    private static FieldCompareMapper fieldCompareMapper = ApplicationContextUtil.getBean(FieldCompareMapper.class);
    private static LastEditedFieldMapper lastEditedFieldMapper = ApplicationContextUtil.getBean(LastEditedFieldMapper.class);
    private static PlatformService platformService = ApplicationContextUtil.getBean(PlatformService.class);

    /**
     * 记录知识字段在关键操作后的变化, 默认记录temp字段变更, 勘误时knowledge附带fieldList;
     *
     * @param operation 关键操作。参照{@link History}
     * @param knowledge 知识
     * @throws IllegalArgumentException 参数不合法
     */
    public static void recordChangesInKnowledgeFields(int operation, Knowledge knowledge) {
        // 参数安全性验证
        if (operation != History.OPERATE_COMMIT && operation != History.OPERATE_REJECT && operation != History.OPERATE_PASS && operation != History.OPERATE_CORRECT) {
            throw new IllegalArgumentException("Illegal operation code: " + operation);
        } else if (Objects.isNull(knowledge) || StringUtils.isEmpty(knowledge.getId())) {
            throw new IllegalArgumentException("Illegal knowledge id is null");
        }
        // 对比字段，计算出提交后变更的字段
        List<FieldCompare> fieldCompareList = getModifiedFieldByKnowledgeId(operation, knowledge);
        // 保存变更后的字段变更数据
        fieldCompareList.stream().peek(item -> item.setOperationDate(LocalDateTimeUtil.getNowAsString()))
                .forEach(fieldCompareMapper::saveBean);
        // 保存完变更数据后把最新的字段存入last_edited_field
        updateLastEditedField(knowledge);
    }

    /**
     * 更新表last_edited_field, 默认记录temp字段变更, 勘误时knowledge附带fieldList;
     *
     * @param knowledge 知识
     */
    public static void updateLastEditedField(Knowledge knowledge) {
        // 默认记录temp字段变更, 勘误时knowledge附带fieldList;
        if (CollectionUtils.isEmpty(knowledge.getKnowledgeFieldList())) {
            String sql = "select * from temp_knowledge_field where knowledge_id = '" + knowledge.getId() + "' and hidden = 0 order by id";
            List<KnowledgeField> tempKnowledgeFields = Lists.newArrayList();
            tempKnowledgeFieldService.getBaseMapper().executeMultiSelect(sql).forEach(tempKnowledgeFields::add);
            knowledge.setKnowledgeFieldList(tempKnowledgeFields);
        }
        lastEditedFieldMapper.executeDelete("delete from last_edited_field where knowledge_id = '" + knowledge.getId() + "'");
        for (KnowledgeField field : knowledge.getKnowledgeFieldList()) {
            LastEditedField lastEditedField = JSON.parseObject(JSON.toJSONString(field), LastEditedField.class);
            lastEditedFieldMapper.saveBean(lastEditedField);
        }
    }

    /**
     * 计算出变化的知识字段, 默认记录temp字段变更, 勘误时knowledge附带fieldList;
     *
     * @param operation 操作
     * @param knowledge 知识对象
     * @return 变化的知识字段List
     */
    private static List<FieldCompare> getModifiedFieldByKnowledgeId(int operation, Knowledge knowledge) {
        // 获取用户名和用户的姓名
        String userId = PMPHAppUtil.getCurrentUserEnName();
        User user = userService.getUserByUserName(userId);
        String userName = user.getName();
        String updateTime = knowledge.getUpdatedTime();

        // 取出需要对比的所有知识字段
        String knowledgeId = knowledge.getId();
        String sql = "";
        if (CollectionUtils.isEmpty(knowledge.getKnowledgeFieldList())) {
            List<KnowledgeField> knowledgeFields = Lists.newArrayList();
            if (operation == History.OPERATE_CORRECT) {
                releasedKnowledgeFieldService.lambdaQuery()
                        .eq(KnowledgeField::getKnowledgeId, knowledgeId).orderByAsc(KnowledgeField::getId).list().forEach(knowledgeFields::add);
            }
            else {
                tempKnowledgeFieldService.lambdaQuery()
                    .eq(KnowledgeField::getKnowledgeId, knowledgeId).orderByAsc(KnowledgeField::getId).list().forEach(knowledgeFields::add);
            }
            knowledge.setKnowledgeFieldList(knowledgeFields);
        }
        List<LastEditedField> oldKnowledgeFields = lastEditedFieldMapper.lambdaQuery().eq(LastEditedField::getKnowledgeId, knowledgeId).list();
        Map<String, LastEditedField> oldKnowledgeFieldMap = new HashMap<>();
        for (LastEditedField oldKnowledgeField : oldKnowledgeFields) {
            oldKnowledgeFieldMap.put(oldKnowledgeField.getName(), oldKnowledgeField);
        }

        // 循环遍历新字段，如果和老字段相同则删掉oldKnowledgeFieldMap中的对应字段后继续遍历
        // 如果和老字段不同或者老字段中不存在当前的新字段，则记录新老字段的变化，并且删除oldKnowledgeFieldMap中对应字段
        // 最后oldKnowledgeFieldMap中剩下的字段是被删除的字段
        List<FieldCompare> fieldCompareList = new ArrayList<>();
        for (KnowledgeField newKnowledgeField : knowledge.getKnowledgeFieldList()) {
            String fieldName = newKnowledgeField.getName();
            if (oldKnowledgeFieldMap.containsKey(fieldName)) {
                LastEditedField oldKnowledgeField = oldKnowledgeFieldMap.get(fieldName);
                if (fieldIsModified(oldKnowledgeField, newKnowledgeField)) {
                    addToFieldCompareList(oldKnowledgeField, newKnowledgeField, fieldCompareList, userId, userName, operation, updateTime);
                }
            } else {
                addToFieldCompareList(null, newKnowledgeField, fieldCompareList, userId, userName, operation, updateTime);
            }
            oldKnowledgeFieldMap.remove(fieldName);
        }

        // 经过上面的循环oldKnowledgeFieldMap中剩下的就是被删除的
        for (Map.Entry<String, LastEditedField> entry : oldKnowledgeFieldMap.entrySet()) {
            LastEditedField oldKnowledgeField = entry.getValue();
            addToFieldCompareList(oldKnowledgeField, null, fieldCompareList, userId, userName, operation, updateTime);
        }

        return fieldCompareList;
    }

    /**
     * 添加字段的新旧变化到数据库
     *
     * @param oldKnowledgeField 修改前的知识字段对象
     * @param newKnowledgeField 修改后的知识字段对象
     * @param fieldCompareList  发生的变化的知识字段对象List
     * @param userId            用户名
     * @param userName          用户姓名
     * @param operation         操作。参照{@link History}
     * @param operationDate     操作日期
     */
    private static void addToFieldCompareList(LastEditedField oldKnowledgeField,
                                              KnowledgeField newKnowledgeField,
                                              List<FieldCompare> fieldCompareList,
                                              String userId,
                                              String userName,
                                              int operation,
                                              String operationDate) {
        FieldCompare fieldCompare = new FieldCompare();
        fieldCompare.setUserId(userId);
        fieldCompare.setUserName(userName);
        if (operation == History.OPERATE_COMMIT) {
            fieldCompare.setOperation("提交");
        } else if (operation == History.OPERATE_REJECT) {
            fieldCompare.setOperation("驳回");
        } else if (operation == History.OPERATE_PASS) {
            fieldCompare.setOperation("通过");
        } else if (operation == History.OPERATE_CORRECT) {
            fieldCompare.setOperation("勘误");
        }
        fieldCompare.setOperationDate(operationDate);

        if (oldKnowledgeField == null) {
            fieldCompare.setKnowledgeFieldId(newKnowledgeField.getId());
            if (StringUtils.isBlank(newKnowledgeField.getDisplayName())) {
                fieldCompare.setKnowledgeFieldName(newKnowledgeField.getName());
            } else {
                fieldCompare.setKnowledgeFieldName(newKnowledgeField.getDisplayName());
            }
            fieldCompare.setKnowledgeId(newKnowledgeField.getKnowledgeId());
            fieldCompare.setOldValue("");
            fieldCompare.setModification("新增");
            if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_STRINGTEXT
                    || newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_TEXTAREA) {
                fieldCompare.setNewValue(newKnowledgeField.getProperty());
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_REFERENCE) {
                List<String> fieldValueList = getNewTag(newKnowledgeField);
                fieldCompare.setNewValue(StringUtils.join(fieldValueList, ";"));
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_RICHEDITOR) {
                fieldCompare.setNewValue(newKnowledgeField.getProperty());
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_DROPDOWNLIST) {
                String ruleItemName = getRuleItemName(newKnowledgeField);
                fieldCompare.setNewValue(ruleItemName);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_DROPMULTILIST) {
                String ruleItemNames = getRuleItemNames(newKnowledgeField);
                fieldCompare.setNewValue(ruleItemNames);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_MULTI_VALUE_INPUT) {
                String inputValues = getMultiValueInput(newKnowledgeField);
                fieldCompare.setNewValue(inputValues);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_ASSOCIATE_CURRENT_KNOWLEDGE_LIB
                    || newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_ASSOCIATE_OTHER_KNOWLEDGE_LIB) {
                String currentKnowledge = getAssociateKnowledge(newKnowledgeField);
                fieldCompare.setNewValue(currentKnowledge);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_ASSOCIATE_PLATFORM) {
                String platforms = getPlatforms(newKnowledgeField);
                fieldCompare.setNewValue(platforms);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_VIDEO) {
                String videoHtml = getVideoHtml(newKnowledgeField);
                fieldCompare.setNewValue(videoHtml);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_FILE) {
                String files = getFiles(newKnowledgeField);
                fieldCompare.setNewValue(files);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_IMG) {
                String imageHtml = getImageHtml(newKnowledgeField);
                fieldCompare.setOldValue(imageHtml);
            }
        } else if (newKnowledgeField == null) {
            fieldCompare.setKnowledgeFieldId(oldKnowledgeField.getId());
            if (StringUtils.isBlank(oldKnowledgeField.getDisplayName())) {
                fieldCompare.setKnowledgeFieldName(oldKnowledgeField.getName());
            } else {
                fieldCompare.setKnowledgeFieldName(oldKnowledgeField.getDisplayName());
            }
            fieldCompare.setKnowledgeId(oldKnowledgeField.getKnowledgeId());
            fieldCompare.setNewValue("");
            fieldCompare.setModification("删除");
            if (oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_STRINGTEXT
                    || oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_TEXTAREA) {
                fieldCompare.setOldValue(oldKnowledgeField.getProperty());
            } else if (oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_REFERENCE) {
                List<String> oldTagList = getOldTag(oldKnowledgeField);
                fieldCompare.setOldValue(StringUtils.join(oldTagList, ";"));
            } else if (oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_RICHEDITOR) {
                fieldCompare.setOldValue(oldKnowledgeField.getProperty());
            } else if (oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_DROPDOWNLIST) {
                String oldRuleItemName = getOldRuleItemName(oldKnowledgeField);
                fieldCompare.setOldValue(oldRuleItemName);
            } else if (oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_DROPMULTILIST) {
                String oldRuleItemNames = getOldRuleItemNames(oldKnowledgeField);
                fieldCompare.setOldValue(oldRuleItemNames);
            } else if (oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_MULTI_VALUE_INPUT) {
                String inputValues = getOldMultiValueInput(oldKnowledgeField);
                fieldCompare.setOldValue(inputValues);
            } else if (oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_ASSOCIATE_CURRENT_KNOWLEDGE_LIB
                    || oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_ASSOCIATE_OTHER_KNOWLEDGE_LIB) {
                String currentKnowledge = getOldAssociateKnowledge(oldKnowledgeField);
                fieldCompare.setOldValue(currentKnowledge);
            } else if (oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_ASSOCIATE_PLATFORM) {
                String platforms = getOldPlatforms(oldKnowledgeField);
                fieldCompare.setOldValue(platforms);
            } else if (oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_VIDEO) {
                String videoHtml = getOldVideoHtml(oldKnowledgeField);
                fieldCompare.setOldValue(videoHtml);
            } else if (oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_FILE) {
                String files = getOldFiles(oldKnowledgeField);
                fieldCompare.setOldValue(files);
            } else if (oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_IMG) {
                String imageHtml = getOldImageHtml(oldKnowledgeField);
                fieldCompare.setOldValue(imageHtml);
            }
        } else {
            fieldCompare.setKnowledgeFieldId(newKnowledgeField.getId());
            if (StringUtils.isBlank(newKnowledgeField.getDisplayName())) {
                fieldCompare.setKnowledgeFieldName(newKnowledgeField.getName());
            } else {
                fieldCompare.setKnowledgeFieldName(newKnowledgeField.getDisplayName());
            }
            fieldCompare.setKnowledgeId(newKnowledgeField.getKnowledgeId());
            fieldCompare.setModification("修改");
            if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_STRINGTEXT
                    || newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_TEXTAREA) {
                fieldCompare.setOldValue(oldKnowledgeField.getProperty());
                fieldCompare.setNewValue(newKnowledgeField.getProperty());
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_REFERENCE) {
                List<String> fieldValueList = getNewTag(newKnowledgeField);
                fieldCompare.setNewValue(StringUtils.join(fieldValueList, ";"));
                List<String> oldTagList = getOldTag(oldKnowledgeField);
                fieldCompare.setOldValue(StringUtils.join(oldTagList, ";"));
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_RICHEDITOR) {
                fieldCompare.setOldValue(oldKnowledgeField.getProperty());
                fieldCompare.setNewValue(newKnowledgeField.getProperty());
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_DROPDOWNLIST) {
                String ruleItemName = getRuleItemName(newKnowledgeField);
                fieldCompare.setNewValue(ruleItemName);
                String oldRuleItemName = getOldRuleItemName(oldKnowledgeField);
                fieldCompare.setOldValue(oldRuleItemName);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_DROPMULTILIST) {
                String ruleItemNames = getRuleItemNames(newKnowledgeField);
                fieldCompare.setNewValue(ruleItemNames);
                String oldRuleItemNames = getOldRuleItemNames(oldKnowledgeField);
                fieldCompare.setOldValue(oldRuleItemNames);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_MULTI_VALUE_INPUT) {
                String inputValues = getMultiValueInput(newKnowledgeField);
                fieldCompare.setNewValue(inputValues);
                String inputValuesOld = getOldMultiValueInput(oldKnowledgeField);
                fieldCompare.setNewValue(inputValuesOld);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_ASSOCIATE_CURRENT_KNOWLEDGE_LIB
                    || newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_ASSOCIATE_OTHER_KNOWLEDGE_LIB) {
                String currentKnowledge = getAssociateKnowledge(newKnowledgeField);
                fieldCompare.setNewValue(currentKnowledge);
                String currentKnowledgeOld = getOldAssociateKnowledge(oldKnowledgeField);
                fieldCompare.setNewValue(currentKnowledgeOld);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_ASSOCIATE_PLATFORM) {
                String platforms = getPlatforms(newKnowledgeField);
                fieldCompare.setNewValue(platforms);
                String platformsOld = getOldPlatforms(oldKnowledgeField);
                fieldCompare.setNewValue(platformsOld);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_VIDEO) {
                String videoHtml = getVideoHtml(newKnowledgeField);
                fieldCompare.setNewValue(videoHtml);
                String videoHtmlOld = getOldVideoHtml(oldKnowledgeField);
                fieldCompare.setNewValue(videoHtmlOld);
            } else if (newKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_FILE) {
                String files = getFiles(newKnowledgeField);
                fieldCompare.setNewValue(files);
                String filesOld = getOldFiles(oldKnowledgeField);
                fieldCompare.setNewValue(filesOld);
            } else if (oldKnowledgeField.getKind() == KnowledgeLibField.FIELD_KIND_IMG) {
                String imageHtml = getImageHtml(newKnowledgeField);
                fieldCompare.setNewValue(imageHtml);
                String imageHtmlOld = getOldImageHtml(oldKnowledgeField);
                fieldCompare.setNewValue(imageHtmlOld);
            }
        }

        fieldCompareList.add(fieldCompare);
    }

    @NotNull
    private static List<String> getNewTag(KnowledgeField newKnowledgeField) {
        List<String> fieldValueList = Lists.newArrayList();
        JSONArray outerArray = JSONArray.parseArray(newKnowledgeField.getProperty());
        if (CollectionUtils.isNotEmpty(outerArray)) {
            // 级联, 后台存储格式为[[1,2,3],[1,2,5]]双重数组, 查询对应的tag;
            Map<String, Tag> tagMap = tagService.selectMap(null);
            for (JSONArray innerArray : outerArray.toJavaList(JSONArray.class)) {
                if (CollectionUtils.isNotEmpty(innerArray)) {
                    String innerStr = innerArray.stream()
                            .map(tagMap::get)
                            .map(Tag::getName)
                            .collect(Collectors.joining("/"));
                    fieldValueList.add(innerStr);
                }
            }
        }
        return fieldValueList;
    }
    @NotNull
    private static List<String> getOldTag(LastEditedField oldKnowledgeField) {
        List<String> fieldValueList = Lists.newArrayList();
        JSONArray outerArray = JSONArray.parseArray(oldKnowledgeField.getProperty());
        if (CollectionUtils.isNotEmpty(outerArray)) {
            // 级联, 后台存储格式为[[1,2,3],[1,2,5]]双重数组, 查询对应的tag;
            Map<String, Tag> tagMap = tagService.selectMap(null);
            for (JSONArray innerArray : outerArray.toJavaList(JSONArray.class)) {
                if (CollectionUtils.isNotEmpty(innerArray)) {
                    String innerStr = innerArray.stream()
                            .map(tagMap::get)
                            .map(Tag::getName)
                            .collect(Collectors.joining("/"));
                    fieldValueList.add(innerStr);
                }
            }
        }
        return fieldValueList;
    }

    private static String getOldImageHtml(LastEditedField oldKnowledgeField) {
        String property = oldKnowledgeField.getProperty();
        return buildImage(property);
    }

    private static String getImageHtml(KnowledgeField newKnowledgeField) {
        String property = newKnowledgeField.getProperty();
        return buildImage(property);
    }

    public static String buildImage(String property) {
        if (StringUtils.isBlank(property)) {
            return "";
        }
        JSONObject jsonObject = null;
        if (!JSONObject.isValid(property)) {
            jsonObject = parseObjectCompatibly(property);
        } else {
            jsonObject = JSONObject.parseObject(property);
        }
        StringBuilder stringBuilder = new StringBuilder();
        String type = jsonObject.getString("type");
        String typeName = ImageUtils.IMAGE_TYPE_NAME_MAP.get(type);
        String typeHtml = "<div>图片类型：" + typeName + "</div>";
        String additional = jsonObject.getString("additional");
        String additionalName = ImageUtils.ADDITIONAL_TYPE_NAME_MAP.get(additional);
        String additionalHtml = "<div>补充类型：" + additionalName + "</div>";
        String classification = jsonObject.getString("classification");
        String className = ImageUtils.IMAGE_CLASSIFICATION_NAME_MAP.get(classification);
        String classHtml = "<div>图片分类：" + className + "</div>";
        String title = jsonObject.getString("title");
        String titleHtml = "<div>图片标题：" + title + "</div>";
        String comment = jsonObject.getString("comment");
        String commentHtml = "<div>注释：" + comment + "</div>";
        stringBuilder.append(typeHtml).append(additionalHtml).append(classHtml).append(titleHtml).append(commentHtml);
        JSONArray jsonArray = jsonObject.getJSONArray("paths");
        if (jsonArray == null) {
            return "";
        }
        for (Object obj : jsonArray) {
            String path = (String) obj;
            String pathHtml = "<div><img src=\"" + path + "\"></div>";
            stringBuilder.append(pathHtml);
        }
        return stringBuilder.toString();
    }

    /**
     * 兼容旧的图片字段数据
     * <p>
     * 旧的图片类型字段数据是以HTML格式存储的，新的图片类型字段数据是以JSON格式存储的。遇到旧的数据需要把旧数据解析成JSON格式的数据。
     * </p>
     * <p>
     * 旧数据的格式如下所示：
     * <code>
     * <p> </p>
     * <p> <img id="20201217090426_422" class="rw_img default"
     * src="/ymer/action/file/showImage?filename=image/knowledge/0001AA100000000HUKPT/0001AA100000000IPECX/20201217090426_422.png"
     * title="默认分类"> </p>
     * <p> <br> </p>
     * <p></p>
     * </code>
     * </p>
     * <p>
     * 解析后的格式如下所示：
     * <code>
     * {
     * "paths": [
     * "/ymer/action/file/showImage?filename=image/knowledge/0001AA100000000HUKPT/0001AA100000000IPECX/PCT_589_4694_20517.jpg"
     * ],
     * "additional": "",
     * "comment": "",
     * "type": "rw_img default",
     * "classification": "",
     * "title": ""
     * }
     * </code>
     * </p>
     *
     * @param property 数据库中图片类型字段值
     * @return 解析后的JSON数据
     */
    private static JSONObject parseObjectCompatibly(@NotNull String property) {
        log.debug("需要兼容性解析的数据：" + property);
        final Document document = Jsoup.parse(property);
        Elements pElements = document.getElementsByTag("p");
        for (Element element : pElements) {
            if (hasImgTag(element)) {
                JSONObject jsonObject = new JSONObject();
                parseIntoJsonObject(element, jsonObject);
                return jsonObject;
            }
        }
        return new JSONObject();
    }

    private static void parseIntoJsonObject(Element element, JSONObject jsonObject) {
        jsonObject.put("additional", "");
        jsonObject.put("comment", "");
        jsonObject.put("classification", "");
        JSONArray jsonArray = new JSONArray();
        for (Element subElement : element.children()) {
            if ("img".equals(subElement.tag().getName())) {
                jsonObject.put("type", subElement.attr("class"));
                jsonObject.put("title", subElement.attr("title"));
                jsonArray.add(subElement.attr("src"));
            }
        }
        jsonObject.put("paths", jsonArray);
        log.debug("兼容解析后的JSON对象：" + jsonObject);
    }

    private static boolean hasImgTag(Element element) {
        for (Element subElement : element.children()) {
            if ("img".equals(subElement.tag().getName())) {
                return true;
            }
        }
        return false;
    }

    private static String getOldFiles(LastEditedField oldKnowledgeField) {
        String property = oldKnowledgeField.getProperty();
        return buildFiles(property);
    }

    @NotNull
    public static String buildFiles(String property) {
        JSONArray jsonArray = JSONArray.parseArray(property);
        StringBuilder stringBuilder = new StringBuilder();
        for (Object obj : jsonArray) {
            JSONObject jsonObject = (JSONObject) obj;
            String fileHtml = "<div><a href=\"" + jsonObject.getString("path") + "&originName=" + jsonObject.getString("name") + "\">" + jsonObject.getString("name") + "</a></div>";
            stringBuilder.append(fileHtml);
        }
        return stringBuilder.toString();
    }

    private static String getOldVideoHtml(LastEditedField oldKnowledgeField) {
        String property = oldKnowledgeField.getProperty();
        return buildVideoHtml(property);
    }

    private static String getOldPlatforms(LastEditedField oldKnowledgeField) {
        String property = oldKnowledgeField.getProperty();
        return buildPlatforms(property);
    }

    @NotNull
    public static String buildPlatforms(String property) {
        List<String> platformIds = JSON.parseArray(property, String.class);
        StringBuilder stringBuilder = new StringBuilder();
        for (String platformId : platformIds) {
            Platform platform = platformService.getById(platformId);
            stringBuilder.append(platform.getName()).append("，");
        }
        return StringUtils.removeEnd(stringBuilder.toString(), "，");
    }

    private static String getOldMultiValueInput(LastEditedField oldKnowledgeField) {
        String property = oldKnowledgeField.getProperty();
        return buildMultiValueInput(property);
    }

    private static String getOldAssociateKnowledge(LastEditedField oldKnowledgeField) {
        String property = oldKnowledgeField.getProperty();
        return buildAssociateKnowledge(property);
    }

    private static String getFiles(KnowledgeField newKnowledgeField) {
        String property = newKnowledgeField.getProperty();
        return buildFiles(property);
    }

    private static String getVideoHtml(KnowledgeField newKnowledgeField) {
        String property = newKnowledgeField.getProperty();
        return buildVideoHtml(property);
    }

    @NotNull
    public static String buildVideoHtml(String property) {
        JSONObject jsonObject = JSONObject.parseObject(property);
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("<div>");
        String title = jsonObject.getString("title");
        stringBuilder.append("<div>").append("标题：").append(title).append("</div>");
        String typeId = jsonObject.getString("type");
        String typeName = "";
        if (!StringUtils.isBlank(typeId)) {
            Tag tag = tagService.getById(typeId);
            typeName = tag.getName();
        }
        stringBuilder.append("<div>").append("类型：").append(typeName).append("</div>");
        JSONArray jsonArray = jsonObject.getJSONArray("paths");
        stringBuilder.append("<div>");
        for (Object obj : jsonArray) {
            String path = (String) obj;
            String videoHtml = "<video src=\"" + path + "\" controls=\"controls\"></video>";
            stringBuilder.append(videoHtml);
        }
        stringBuilder.append("</div>");
        stringBuilder.append("</div>");
        return stringBuilder.toString();
    }

    private static String getPlatforms(KnowledgeField newKnowledgeField) {
        String property = newKnowledgeField.getProperty();
        return buildPlatforms(property);
    }

    private static String getAssociateKnowledge(KnowledgeField newKnowledgeField) {
        String property = newKnowledgeField.getProperty();
        return buildAssociateKnowledge(property);
    }

    @NotNull
    public static String buildAssociateKnowledge(String property) {
        JSONArray jsonArray = JSONArray.parseArray(property);
        StringBuilder stringBuilder = new StringBuilder();
        for (Object obj : jsonArray) {
            JSONObject object = (JSONObject) obj;
            stringBuilder.append(object.get("name")).append("，");
        }
        return StringUtils.removeEnd(stringBuilder.toString(), "，");
    }

    private static String getMultiValueInput(KnowledgeField newKnowledgeField) {
        String property = newKnowledgeField.getProperty();
        return buildMultiValueInput(property);
    }

    @NotNull
    public static String buildMultiValueInput(String property) {
        JSONArray jsonArray = JSONArray.parseArray(property);
        StringBuilder stringBuilder = new StringBuilder();
        for (Object obj : jsonArray) {
            String value = (String) obj;
            stringBuilder.append(value).append("，");
        }
        return StringUtils.removeEnd(stringBuilder.toString(), "，");
    }

    @NotNull
    private static String getOldRuleItemNames(LastEditedField oldKnowledgeField) {
        String ruleId = oldKnowledgeField.getKindValue();
        return buildRuleItemNames(ruleId, oldKnowledgeField.getProperty());
    }

    @NotNull
    private static String buildRuleItemNames(String ruleId, String property) {
        if (StringUtils.isBlank(ruleId)) {
            throw new RuntimeException("多选下拉框列表不能为空");
        }
        if (StringUtils.isBlank(property)) {
            return "";
        }
        String values = property.replace(",", "','");
        List<RuleItem> ruleItemList = ruleItemService.lambdaQuery().in(RuleItem::getId, Arrays.asList(property.split(","))).orderByAsc(RuleItem::getIdx).list();
        return ruleItemList.stream().map(RuleItem::getName).collect(Collectors.joining(","));
    }

    private static String getOldRuleItemName(LastEditedField oldKnowledgeField) {
        String ruleId = oldKnowledgeField.getKindValue();
        String property = oldKnowledgeField.getProperty();
        if (StringUtils.isBlank(ruleId)) {
            throw new RuntimeException("单选下拉框列表不能为空");
        }
        if (StringUtils.isBlank(property)) {
            return "";
        }
        RuleItem ruleItem = ruleItemService.getById(property);
        return Objects.isNull(ruleItem) ? "" : ruleItem.getName();
    }

    @NotNull
    private static String getRuleItemNames(KnowledgeField newKnowledgeField) {
        String ruleId = newKnowledgeField.getKindValue();
        return buildRuleItemNames(ruleId, newKnowledgeField.getProperty());
    }

    private static String getRuleItemName(KnowledgeField newKnowledgeField) {
        String ruleItemId = newKnowledgeField.getProperty();
        String ruleId = newKnowledgeField.getKindValue();
        if (StringUtils.isBlank(ruleId)) {
            throw new RuntimeException("单选下拉框列表不能为空");
        }
        if (StringUtils.isBlank(ruleItemId)) {
            return "";
        }
        RuleItem ruleItem = ruleItemService.getById(ruleItemId);
        return Objects.isNull(ruleItem) ? "" : ruleItem.getName();
    }

    /**
     * 判断一个知识字段是否有变化
     *
     * @param oldKnowledgeField 修改前的知识字段
     * @param newKnowledgeField 修改后的知识字段
     * @return true：有变化，false：没有变化
     */
    private static boolean fieldIsModified(LastEditedField oldKnowledgeField, KnowledgeField newKnowledgeField) {
        boolean propertyModified;
        if (oldKnowledgeField.getProperty() == null) {
            propertyModified = newKnowledgeField.getProperty() != null;
        } else {
            propertyModified = !oldKnowledgeField.getProperty().equals(newKnowledgeField.getProperty());
        }
        boolean tagIdModified;
        if (oldKnowledgeField.getKindValue() == null) {
            tagIdModified = newKnowledgeField.getKindValue() != null;
        } else {
            tagIdModified = !oldKnowledgeField.getKindValue().equals(newKnowledgeField.getKindValue());
        }

        return propertyModified || tagIdModified;
    }
}
